/*
    KMC Simulation
    Copyright (c) 2013-2014 Filip Rozbořil

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "includes.h"
#include "Exception.h"

#ifdef SEGF_DEBUG
	#define DEBUG
	#define DEBUG_FAST
#endif

#ifdef DEBUG
	#define TRACE true
#else
	#define TRACE false
#endif

#ifdef DEBUG_FAST
	#define Trace(x) \
		Utils::bufferLine(x)
#else
	#define Trace(x) \
		do { if (TRACE) cout << x << endl; } while (false)
#endif
 
namespace Utils
{
	uint64_t getPrngKey(uint64_t index);
	
#ifdef DEBUG_FAST
	void bufferLine(const string& message);
 	void printBuffer();
#endif

	template<typename T> const char* typeName(void);
	template<typename T> const char* typeName(T type) { return typeName<T>(); }

#define REFLECTION_REGISTER_TYPE(type) \
    template <> inline const char* typeName<type>(void) { return #type; } 
    
	REFLECTION_REGISTER_TYPE(uint32_t)
	REFLECTION_REGISTER_TYPE(uint64_t)
	REFLECTION_REGISTER_TYPE(double)

	template<typename T>
	void convertFromString(string s, T &x)
	{
		istringstream i(s);
	 	if (!(i >> x))
	 	{
			throw Exception("Cannot convert '" + s + "' to type '" + typeName(x) + "'");
		}
	}
	
	template<typename T>
	string convertToString(T x)
	{
		stringstream ss;
		ss << x;
		return ss.str();
	}
	
	bool isPowerOfTwo(uint32_t x);
	
#define assert(expr) \
	if(!(expr)) throw Exception("Assertation failed: " #expr)

}

inline bool Utils :: isPowerOfTwo(uint32_t x)
{
	return (x & (x - 1)) == 0;
}

